package cn.fintecher.gis.service;

import cn.fintecher.gis.entity.LayerInfo;
import cn.fintecher.gis.entity.LayerRelation;
import cn.fintecher.gis.entity.QLayerInfo;
import cn.fintecher.gis.entity.QLayerRelation;
import cn.fintecher.gis.enums.CommonShow;
import cn.fintecher.gis.enums.LayerRelate;
import cn.fintecher.gis.enums.Pellucidity;
import cn.fintecher.gis.exception.BadRequestException;
import cn.fintecher.gis.geoserver.GeoManagerService;
import cn.fintecher.gis.model.ParsingShpResults;
import cn.fintecher.gis.model.request.LayerInfoCreateRequest;
import cn.fintecher.gis.model.request.LayerInfoRequest;
import cn.fintecher.gis.model.response.LayerInfoResponse;
import cn.fintecher.gis.model.session.SessionModel;
import cn.fintecher.gis.postgis.PostGISService;
import cn.fintecher.gis.respository.LayerInfoRepository;
import cn.fintecher.gis.respository.LayerRelationRepository;
import cn.fintecher.gis.utils.BeanUtils;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

@Service("layerInfoService")
public class LayerInfoService {

    private final Logger log = LoggerFactory.getLogger(LayerInfoService.class);

    @Autowired
    private LayerInfoRepository layerInfoRepository;

    @Autowired
    private PostGISService postGISService;

    @Autowired
    private GeoManagerService geoManagerService;

    @Autowired
    private LayerRelationRepository layerRelationRepository;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LogInfoService logInfoService;

    /**
     * 查询图层信息分页
     *
     * @param request
     * @param pageable
     * @return
     */
    public Page<LayerInfoResponse> getLayerInfoAll(LayerInfoRequest request, Pageable pageable) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (StringUtils.isNotBlank(request.getLayerName())) {
            booleanBuilder.and(QLayerInfo.layerInfo.layerName.like("%".concat(request.getLayerName().trim()).concat("%")));
        }
        if (request.getGroupId() != null && !request.getGroupId().isEmpty()) {
            booleanBuilder.and(QLayerInfo.layerInfo.groupId.eq(request.getGroupId().trim()));
        }
        if (request.getLayerSpace() != null && !request.getLayerSpace().isEmpty()) {
            booleanBuilder.and(QLayerInfo.layerInfo.layerSpace.eq(request.getLayerSpace().trim()));
        }
        if (request.getCreateDate() != null) {
            LocalDate dateTime = LocalDate.parse(request.getCreateDate(), DateTimeFormat.forPattern("yyyy-MM-dd"));
            booleanBuilder.and(QLayerInfo.layerInfo.createDate.between(dateTime.toDate(), dateTime.plusDays(1).toDate()));
        }
        Page<LayerInfo> layerInfoPage = layerInfoRepository.findAll(booleanBuilder, pageable);
        Page<LayerInfoResponse> page=  layerInfoPage.map(layerInfo -> {
            LayerInfoResponse layerInfoResponse=new LayerInfoResponse();
            BeanUtils.copyPropertiesIgnoreNull(layerInfo,layerInfoResponse);
            return layerInfoResponse;
        });

        return page;
    }

    /**
     * 查询所有的图层信息不分页
     *
     * @return
     */
    public List<LayerInfoResponse> queryLayerInfoList(String layerSpace) {
        List<LayerInfo> layerInfoList = new ArrayList<>();
        if (layerSpace != null && !layerSpace.isEmpty()) {
            Iterable<LayerInfo> iterable = layerInfoRepository.findAll(QLayerInfo.layerInfo.layerSpace.eq(layerSpace));
            layerInfoList =   Lists.newArrayList(iterable);;
        } else {
            layerInfoList = layerInfoRepository.findAll();
        }
        List<LayerInfoResponse> list = new ArrayList<>();
        for (LayerInfo layerInfo : layerInfoList) {
            LayerInfoResponse layerInfoResponse = new LayerInfoResponse();
            BeanUtils.copyProperties(layerInfo, layerInfoResponse);
            layerInfoResponse.setOperatorName(layerInfo.getCreateName());
            list.add(layerInfoResponse);
        }
        //按照时间进行升序排序
        Collections.sort(list, new Comparator<LayerInfoResponse>() {
            @Override
            public int compare(LayerInfoResponse o1, LayerInfoResponse o2) {
                if (o1.getSort() > o2.getSort()) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        return list;
    }

    /**
     * 查询图层类型对应的图层code
     *
     * @return
     */
    public List<LayerRelation> getLayerRelation(LayerRelate type) {
        if(type != null){
            Iterator<LayerRelation> iterator = layerRelationRepository.findAll(QLayerRelation.layerRelation.type.eq(type)).iterator();
            return Lists.newArrayList(iterator);
        }else{
            List<LayerRelation> layerRelations = layerRelationRepository.findAll();
            return layerRelations;
        }

    }

    /**
     * 根据id查询图层信息
     *
     * @param id
     * @return
     */
    public LayerInfoResponse queryLayerInfoById(String id) {
        LayerInfoResponse layerInfoResponse = new LayerInfoResponse();
        layerInfoRepository.findById(id).ifPresent(layerInfo -> {
            BeanUtils.copyPropertiesIgnoreNull(layerInfo, layerInfoResponse);
            layerInfoResponse.setOperatorName(layerInfo.getCreateName());
            return;
        });
        return layerInfoResponse;
    }

    /**
     * 图层信息的维护
     *
     * @param request
     */
    @Transactional
    public LayerInfo createLayerInfo(LayerInfoCreateRequest request, SessionModel sessionModel) throws IOException {
        LayerInfo layerInfo = new LayerInfo();
        BeanUtils.copyPropertiesIgnoreNull(request, layerInfo);
        layerInfo.setOpacity(Pellucidity.FALSE);
        layerInfo.setCreateOperator(sessionModel.getId());
        layerInfo.setCreateName(sessionModel.getUsername());
        layerInfo.setCreateDate(new Date());

        setLayerInfo(request, layerInfo);

        if (request.getLayerShow().equals(CommonShow.NO)) {
            LayerRelation layerRelation = layerRelationRepository.findOne(QLayerRelation.layerRelation.type
                    .eq(request.getLayerType())).orElse(new LayerRelation());
            if (Objects.isNull(layerRelation)) {
                layerInfo.setLayerShow(CommonShow.YES);
            } else {
                if (StringUtils.isEmpty(layerRelation.getLayerCode())) {
                    layerInfo.setLayerShow(CommonShow.YES);
                }
            }
        } else {
            Iterator<LayerInfo> infoIterator = layerInfoRepository.findAll(QLayerInfo.layerInfo.layerType.eq(layerInfo.getLayerType())).iterator();
            List<LayerInfo> layerInfos = new ArrayList<>();
            while (infoIterator.hasNext()) {
                LayerInfo layer = infoIterator.next();
                layer.setLayerShow(CommonShow.NO);
                layerInfos.add(layer);
            }
            layerInfoRepository.saveAll(layerInfos);
        }
        layerInfo = layerInfoRepository.saveAndFlush(layerInfo);
        saveLayerRelation(request, layerInfo);
        return layerInfo;
    }


    /**
     * 处理图层关系
     *
     * @param request
     * @param layerInfo
     */
    private void saveLayerRelation(LayerInfoCreateRequest request, LayerInfo layerInfo) {
        if (request.getLayerType() != null) {
            BooleanBuilder builder = new BooleanBuilder();
            QLayerRelation qLayerRelation = QLayerRelation.layerRelation;
            builder.and(qLayerRelation.type.eq(request.getLayerType()));
            Iterator<LayerRelation> iterator = layerRelationRepository.findAll(builder).iterator();
            List<LayerRelation> layerRelations = Lists.newArrayList(iterator);
            List<LayerRelation> relationList = new ArrayList<>();
            if (layerRelations == null || layerRelations.isEmpty()) {
                LayerRelation layerRelation = new LayerRelation();
                layerRelation.setLayerCode(layerInfo.getLayerCode());
                layerRelation.setType(request.getLayerType());
                String value = messageSource.getMessage(request.getLayerType().getMessageKey(request.getLayerType()), null, Locale.CHINA);
                layerRelation.setName(value);
                relationList.add(layerRelation);
            }
            if (layerInfo.getLayerShow().equals(CommonShow.YES)) {
                for (LayerRelation layerRelation : layerRelations) {
                    if (StringUtils.isNotEmpty(layerRelation.getLayerCode())) {
                        BooleanBuilder booleanBuilder = new BooleanBuilder();
                        QLayerInfo qLayerInfo = QLayerInfo.layerInfo;
                        booleanBuilder.and(qLayerInfo.layerType.eq(request.getLayerType()));
                        booleanBuilder.and(qLayerInfo.layerCode.eq(layerRelation.getLayerCode()));
                        LayerInfo layerInfo1 = layerInfoRepository.findOne(booleanBuilder).orElse(new LayerInfo());
                        if (Objects.nonNull(layerInfo1)) {
                            layerInfo1.setLayerShow(CommonShow.NO);
                            layerInfoRepository.save(layerInfo);
                        }
                    }
                    layerRelation.setLayerCode(layerInfo.getLayerCode());
                    relationList.add(layerRelation);
                }
            }
            layerRelationRepository.saveAll(relationList);
        }
    }


    /**
     * 修改图层状态
     *
     * @param id
     * @param layerShow
     */
    public void adjustShow(String id, CommonShow layerShow) {
        Optional<LayerInfo> optionalLayerInfo = layerInfoRepository.findById(id);
        if (!optionalLayerInfo.isPresent()) {
            throw new BadRequestException("layerInfo", "this.layerInfo.is.not.exist");
        }
        LayerInfo layerInfo = optionalLayerInfo.get();

        if (layerInfo.getLayerShow().equals(CommonShow.YES)) { //原来是主图层
            if (layerShow.equals(CommonShow.NO)) { //修改为普通图层
                LayerRelation layerRelation = layerRelationRepository.findOne(QLayerRelation.layerRelation.type.eq(layerInfo.getLayerType())).get();
                layerRelation.setLayerCode(null);
                layerRelationRepository.save(layerRelation);
            }
        } else { //原来是副图层
            if (layerShow.equals(CommonShow.YES)) { //修改成主图层
                LayerRelation layerRelation = layerRelationRepository.findOne(QLayerRelation.layerRelation.type.eq(layerInfo.getLayerType())).orElse(new LayerRelation());
                if (Objects.isNull(layerRelation)) {
                    layerRelation.setType(layerInfo.getLayerType());
                    String value = messageSource.getMessage(layerInfo.getLayerType().getMessageKey(layerInfo.getLayerType()), null, Locale.CHINA);
                    layerRelation.setName(value);
                } else {
                    if (StringUtils.isNotEmpty(layerRelation.getLayerCode())) {
                        LayerInfo layer = layerInfoRepository.findOne(QLayerInfo.layerInfo.layerCode.eq(layerRelation.getLayerCode())).orElse(new LayerInfo());
                        if (Objects.nonNull(layer)) {
                            layer.setLayerShow(CommonShow.NO);
                            layerInfoRepository.save(layer);
                        }
                    }
                }
                layerRelation.setLayerCode(layerInfo.getLayerCode());
                layerRelationRepository.save(layerRelation);
            }
        }
        layerInfo.setLayerShow(layerShow);
        layerInfoRepository.save(layerInfo);
    }



    /**
     * 处理图层中的图层字段信息赋值
     * @param request
     * @param layerInfo
     * @throws IOException
     */
    private void setLayerInfo(LayerInfoCreateRequest request, LayerInfo layerInfo) throws IOException {
        String fileId = request.getFileId();
        ParsingShpResults result1 = postGISService.uploadShp(fileId);
        if (!result1.getIsSuccess()) {
            throw new BadRequestException("importShp", result1.getMessage());
        }

        ParsingShpResults result2 = geoManagerService.releaseLayer(fileId, result1.getCrs(), request.getStyleNames(), request.getLayerSpace());
        if (!result2.getIsSuccess()) {
            throw new BadRequestException("importShp", result2.getMessage());
        }
        layerInfo.setLayerCode(fileId);
        layerInfo.setTableName(fileId);
        layerInfo.setLayerSpace(request.getLayerSpace());
    }

    /**
     * 图层的维护
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public void editLayerInfo(LayerInfoCreateRequest request, SessionModel sessionModel) throws Exception {
        Optional<LayerInfo> optionalLayerInfo = layerInfoRepository.findById(request.getId());
        if (!optionalLayerInfo.isPresent()) {
            throw new BadRequestException("layerInfo", "this.layerInfo.is.not.exist");
        }
        LayerInfo layerInfo = optionalLayerInfo.get();
        BeanUtils.copyPropertiesIgnoreNull(request, layerInfo);
        setLayerInfo(request, layerInfo);
        layerInfoRepository.saveAndFlush(layerInfo);
        if (layerInfo.getLayerShow().equals(CommonShow.YES)) {
            saveLayerRelation(request, layerInfo);
        }
    }



    /**
     * 根据图册id删除图层信息
     *
     * @param layerId
     */
    @Transactional
    public void deleteLayerInfoById(String layerId, String workSpace) throws IOException {
        LayerInfo layerInfo = layerInfoRepository.findById(layerId).orElseThrow(() -> new BadRequestException("", "this.layerInfo.is.not.exist"));
        geoManagerService.deleteLayer(layerInfo.getLayerCode(), workSpace);
        postGISService.removeSchema(layerInfo.getLayerCode());
        if (layerInfo.getLayerShow().equals(CommonShow.YES)) {
            LayerRelation layerRelation = layerRelationRepository.findOne(QLayerRelation.layerRelation.layerCode.eq(layerInfo.getLayerCode())).orElse(new LayerRelation());
            if (Objects.nonNull(layerRelation)) {
                layerRelation.setLayerCode(null);
                BooleanBuilder builder = new BooleanBuilder();
                QLayerInfo qLayerInfo = QLayerInfo.layerInfo;
                builder.and(qLayerInfo.layerType.eq(layerInfo.getLayerType()));
                builder.and(qLayerInfo.layerCode.notIn(layerInfo.getLayerCode()));
                Iterator<LayerInfo> iterator = layerInfoRepository.findAll(builder).iterator();
                if (iterator.hasNext()) {
                    LayerInfo layer = iterator.next();
                    layerRelation.setLayerCode(layer.getLayerCode());
                    layer.setLayerShow(CommonShow.YES);
                    layerInfoRepository.save(layer);
                }
                layerRelationRepository.save(layerRelation);
            }
        }
        logInfoService.addLog("LayerInfoController", "deleteLayerInfoById",
                "layerId=" + layerId + ",workSpace=" + workSpace, "删除的图层名称是:" + layerInfo.getLayerName());
        layerInfoRepository.delete(layerInfo);
    }
}
